#include "client/RequestQueue.h"
#include <boost/thread/locks.hpp>
#include <boost/bind.hpp>
#include <glog/logging.h>
namespace client {
RequestQueue* RequestQueue::self_ = NULL;
void RequestQueue::Create(boost::shared_ptr<chat::ChatServiceClient> client) {
  self_ = new RequestQueue(client);
}
RequestQueue::RequestQueue(boost::shared_ptr<chat::ChatServiceClient> client) : client_(client) {
  
}
RequestQueue* RequestQueue::Instance() {
  return self_;
}
bool RequestQueue::IsQueueFull() const {
  return queue_.size() > kMaxPendingReq;
}
boost::function<void ()> RequestQueue::Pop() {
  {
    boost::unique_lock<boost::mutex> lock(mutex_);
    cond_.wait(lock);
  }
  {
    boost::lock_guard<boost::mutex> lock(mutex_);
    boost::function<void ()> req = queue_.front();
    queue_.pop();
    return req;
  }
}
template<typename ReqType>
void RequestQueue::Schedule(const ReqType& req) {
  LOG(ERROR) << "schedule invalid request type";
}
template <>
void RequestQueue::Schedule(const chat::SendMsgReq& req) {
  boost::lock_guard<boost::mutex> lock(mutex_);
  if (IsQueueFull()) return;
  queue_.push(boost::bind(&chat::ChatServiceClient::SendMsg, client_, req));
  cond_.notify_one();
}
template <>
void RequestQueue::Schedule(const chat::SendEmptyRequestReq& req) {
  boost::lock_guard<boost::mutex> lock(mutex_);
  if (IsQueueFull()) return;
  queue_.push(boost::bind(&chat::ChatServiceClient::SendEmptyRequest, client_, req));
  cond_.notify_one();
}
}
